package com.datasure.cloudsure.redis.builder;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.util.List;

/**
 * 根据配置属性构建RedisConnectionFactoryBuilder
 * 根据配置文件中的配置
 * RedisConnectionFactory
 */
public class RedisConnectionFactoryBuilder {

    /**
     * 动态构建ConnectionFactory
     *
     * @param properties 配置属性
     * @return
     */
    public static RedisConnectionFactory build(RedisProperties properties) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = getRedisStandaloneConfiguration(properties);
        RedisClusterConfiguration redisClusterConfiguration = getRedisClusterConfiguration(properties);
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder
                builder = LettucePoolingClientConfiguration.builder();
        if (properties.getTimeout() != null) {
            // 设置超时时间
            Duration timeout = properties.getTimeout();
            builder.commandTimeout(timeout).shutdownTimeout(timeout);
        }
        // 连接池构造器
        // 客户端连接池
        builder.poolConfig(poolConfig(properties));
        //通过构造器来构造lettuce客户端配置
        LettucePoolingClientConfiguration lettuceClientConfiguration = builder.build();
        if (properties.getCluster() == null) {
            //单机配置 + 客户端配置 = lettuce连接工厂
            LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
            lettuceConnectionFactory.afterPropertiesSet();
            return lettuceConnectionFactory;
        } else {
            //集群配置 + 客户端配置 = lettuce连接工厂
            LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
            lettuceConnectionFactory.afterPropertiesSet();
            return lettuceConnectionFactory;
        }
    }

    /**
     * 单机配置信息
     *
     * @param properties
     * @return
     */
    public static RedisStandaloneConfiguration getRedisStandaloneConfiguration(RedisProperties properties) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        if (properties.getCluster() == null) {
            redisStandaloneConfiguration.setHostName(properties.getHost());
            redisStandaloneConfiguration.setPort(properties.getPort());
            if (!StringUtils.isEmpty(properties.getPassword())) {
                redisStandaloneConfiguration.setPassword(properties.getPassword());
            }
            if (properties.getDatabase() != 0) {
                redisStandaloneConfiguration.setDatabase(properties.getDatabase());
            }
        }
        return redisStandaloneConfiguration;
    }

    /**
     * 集群配置信息
     *
     * @param properties
     * @return
     */
    public static RedisClusterConfiguration getRedisClusterConfiguration(RedisProperties properties) {
        //创建redis集群配置类
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        if (properties.getCluster() != null) {
            List<String> nodes = properties.getCluster().getNodes();
            //redis集群密码
            if (!StringUtils.isEmpty(properties.getPassword())) {
                redisClusterConfiguration.setPassword(properties.getPassword());
            }
            for (String node : nodes) {
                String[] split = node.split(":");
                redisClusterConfiguration.clusterNode(split[0], Integer.parseInt(split[1]));
            }
            if (properties.getCluster().getMaxRedirects() > 0) {
                redisClusterConfiguration.setMaxRedirects(properties.getCluster().getMaxRedirects());
            }
        }
        return redisClusterConfiguration;
    }


    /**
     * 动态配置连接池
     *
     * @param properties
     * @return
     */
    public static GenericObjectPoolConfig poolConfig(RedisProperties properties) {
        RedisProperties.Pool jedisPool = properties.getJedis().getPool();
        RedisProperties.Pool lettucePool = properties.getLettuce().getPool();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        if (jedisPool != null) {
            poolConfig.setMaxTotal(jedisPool.getMaxActive());
            poolConfig.setMaxIdle(jedisPool.getMaxIdle());
            poolConfig.setMinIdle(jedisPool.getMinIdle());
            if (jedisPool.getTimeBetweenEvictionRuns() != null) {
                poolConfig.setTimeBetweenEvictionRunsMillis(jedisPool.getTimeBetweenEvictionRuns().toMillis());
            }
            if (jedisPool.getMaxWait() != null) {
                poolConfig.setMaxWaitMillis(jedisPool.getMaxWait().toMillis());
            }
        }
        if (lettucePool != null) {
            poolConfig.setMaxTotal(lettucePool.getMaxActive());
            poolConfig.setMaxIdle(lettucePool.getMaxIdle());
            poolConfig.setMinIdle(lettucePool.getMinIdle());
            if (lettucePool.getTimeBetweenEvictionRuns() != null) {
                poolConfig.setTimeBetweenEvictionRunsMillis(lettucePool.getTimeBetweenEvictionRuns().toMillis());
            }
            if (lettucePool.getMaxWait() != null) {
                poolConfig.setMaxWaitMillis(lettucePool.getMaxWait().toMillis());
            }
        }
        return poolConfig;
    }
}